home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / comstr.exe / COMSTREA.CPP < prev    next >
Text File  |  1993-01-03  |  12KB  |  599 lines

  1. #if !defined( __DOS_H )
  2. #include <Dos.h>
  3. #endif    // __DOS_H
  4.  
  5. #if !defined( __COMSTREAM_H )
  6. #include "Comstream.h"
  7. #endif    // __COMSTREAM_H
  8.  
  9. #if !defined( __TIMER_H )
  10. #include "Timer.h"
  11. #endif    // __TIMER_H
  12.  
  13. #define TESTPORTBIT(x,y) (inportb(x) & y)
  14.  
  15. #define IER    1
  16. #define IIR    2
  17. #define LCR    3
  18. #define LSR    5
  19. #define MSR    6
  20.  
  21. #define    MODEMFAIL    0
  22. #define XMTEMPTY    2
  23. #define READFULL    4
  24. #define LINEFAIL    6
  25.  
  26. #define    RXRDY        1
  27. #define TBE            32
  28. #define TXE            64
  29.  
  30. #define RTS            2
  31. #define GP01        4
  32. #define GP02        8
  33. #define    LOOPBACK    16
  34.  
  35. #define CTS            16
  36.  
  37. #define DLAB        128
  38.  
  39. ComDef::ComDef( int n )
  40.     {
  41.     if( n >= 0 && n < 4 )
  42.         {
  43.         unsigned far *pPort = (unsigned far *) MK_FP( 0, 0x400 );
  44.         portAddr = pPort[n];
  45.         }
  46.     else
  47.         portAddr = 0;
  48.  
  49.     if( portAddr != 0 )
  50.         {
  51.         irqAddr = ( n & 1 ) ? 0x0B : 0x0C;
  52.         picMask = ( n & 1 ) ? 0x08 : 0x10;
  53.         oldhandler = getvect( irqAddr );
  54.         }
  55.     else
  56.         {
  57.         irqAddr = picMask = 0;
  58.         oldhandler = 0;
  59.         }
  60.     owner = 0;
  61.     }
  62.  
  63. ComDef::~ComDef()
  64.     {
  65.     clrCombuf();
  66.     }
  67.  
  68. void ComDef::setParams( int aPort, int aIRQ, int aMask )
  69.     {
  70.     if( owner != 0 )    return;
  71.  
  72.     if( oldhandler && irqAddr )
  73.         setvect( irqAddr, oldhandler );
  74.     oldhandler = 0;
  75.  
  76.     portAddr = aPort;
  77.     irqAddr = aIRQ;
  78.     picMask = aMask;
  79.     oldhandler = getvect( irqAddr );
  80.     }
  81.  
  82. int ComDef::setCombuf( combuf *cb )
  83.     {
  84.     void interrupt far (*handler)(...);
  85.  
  86.     if( owner != 0 )    return 0;
  87.  
  88.     if( irqAddr == 0x0B )
  89.         handler = combuf::handler0x0B;
  90.     else if( irqAddr == 0x0C )
  91.         handler = combuf::handler0x0C;
  92.     else
  93.         return 0;
  94.  
  95.     owner = cb;
  96.     outportb( portAddr+MCR, 0 );
  97.     outportb( portAddr+IER, 0 );
  98.     outportb( portAddr+LCR, inportb(portAddr+LCR) & 0x3F );
  99.     for( int i = 0; i < 7; i++ )
  100.         inportb( portAddr+i );
  101.     setvect( irqAddr, handler );
  102.     outportb( 0x21, (inportb(0x21) & ~picMask) );
  103.     outportb( portAddr+MCR, GP02 );
  104.     outportb( portAddr+IER, 0x0F );
  105.     return 1;
  106.     }
  107.  
  108. void ComDef::clrCombuf()
  109.     {
  110.     if( owner == 0 )    return;
  111.     if( irqAddr != 0x0B && irqAddr != 0x0C )
  112.         return;
  113.     outportb( 0x21, (inportb(0x21) | picMask) );
  114.     outportb( portAddr+MCR, 0 );
  115.     outportb( portAddr+IER, 0 );
  116.     setvect( irqAddr, oldhandler );
  117.     owner = 0;
  118.     }
  119.  
  120. ComDef combuf::def[] = { 0, 1, 2, 3 };
  121.  
  122. void interrupt far combuf::handler0x0B(...)
  123.     {
  124.     combuf *owner;
  125.     int i, port, cause, data;
  126.  
  127.     for( i = 0; i < NUMBEROFPORTS; i++ )
  128.         if( (owner = combuf::def[i].owner) != 0 && combuf::def[i].irqAddr == 0x0B )
  129.             {
  130.             port = combuf::def[i].portAddr;
  131.             cause = inportb( port+IIR ) & 0x0F;
  132.             if( (cause & 1) == 0 )
  133.                 {
  134.                 if( cause == READFULL )            data = inportb( port );
  135.                 else if( cause == LINEFAIL )    data = inportb( port+LSR );
  136.                 else if( cause == MODEMFAIL )    data = inportb( port+MSR );
  137.                 outportb( 0x20, 0x20 );
  138.                 owner->handleIRQ( port, cause, data );
  139.                 return;
  140.                 }
  141.             }
  142.     outportb( 0x20, 0x20 );
  143.     }
  144.  
  145.  
  146. void interrupt far combuf::handler0x0C(...)
  147.     {
  148.     combuf *owner;
  149.     int i, port, cause, data;
  150.  
  151.     for( i = 0; i < NUMBEROFPORTS; i++ )
  152.         if( (owner = combuf::def[i].owner) != 0 && combuf::def[i].irqAddr == 0x0C )
  153.             {
  154.             port = combuf::def[i].portAddr;
  155.             cause = inportb( port+IIR ) & 0x0F;
  156.             if( (cause & 1) == 0 )
  157.                 {
  158.                 if( cause == READFULL )            data = inportb( port );
  159.                 else if( cause == LINEFAIL )    data = inportb( port+LSR );
  160.                 else if( cause == MODEMFAIL )    data = inportb( port+MSR );
  161.                 outportb( 0x20, 0x20 );
  162.                 owner->handleIRQ( port, cause, data );
  163.                 return;
  164.                 }
  165.             }
  166.     outportb( 0x20, 0x20 );
  167.     }
  168.  
  169. void combuf::handleIRQ( int port, int cause, int data )
  170.     {
  171.     if( cause == READFULL )
  172.         insertc( data );
  173.     else if( cause == XMTEMPTY )
  174.         {
  175.         int ch = extractc();
  176.         if( ch != EOF )
  177.             {
  178.             if( ibdelay_ != 0 || (ch == '\r' && ildelay_ != 0) )
  179.                 {
  180.                 long l = (ch == '\r' && ildelay_ != 0) ? ildelay_ : ibdelay_;
  181.                 int n = inportb( 0x21 );
  182.                 outportb( 0x21, n | 0x18 );
  183.                 enable();
  184.                 Timer timer;
  185.                 while( timer.elapsed() < l );
  186.                 disable();
  187.                 outportb( 0x21, n );
  188.                 }
  189.             outportb( port, ch );
  190.             }
  191.         }
  192.     else if( cause == LINEFAIL )
  193.         errFlags |= ( data & (OR | FE | PE | BI) );
  194.     }
  195.  
  196. combuf::combuf( char *b, int inlen, int outlen ) : streambuf( b, inlen+outlen )
  197.     {
  198.     inSize = inlen;
  199.     errFlags = 0;
  200.     options = 0;
  201.     offs_ = EOF;
  202.     setTimeout( 300 );
  203.     setInterCharDelay( 0 );
  204.     setInterLineDelay( 0 );
  205.     }
  206.  
  207. combuf::combuf()
  208.     {
  209.     inSize = 0;
  210.     errFlags = 0;
  211.     options = 0;
  212.     offs_ = EOF;
  213.     setTimeout( 300 );
  214.     setInterCharDelay( 0 );
  215.     setInterLineDelay( 0 );
  216.     }
  217.  
  218. combuf::~combuf()
  219.     {
  220.     setPort();
  221.     }
  222.  
  223. streambuf *combuf::setbuf( signed char *b, int len )
  224.     {
  225.     streambuf::setbuf( b, len );
  226.     inSize = len/2;
  227.     return this;
  228.     }
  229.  
  230. combuf *combuf::setbuf( char *b, int inlen, int outlen )
  231.     {
  232.     streambuf::setbuf( b, inlen+outlen );
  233.     inSize = inlen;
  234.     return this;
  235.     }
  236.  
  237. int combuf::underflow()
  238.     {
  239.     Timer timer;
  240.  
  241.     if( offs_ == EOF )    return EOF;
  242.  
  243.     if( in_avail() == 0 )
  244.         {
  245.         while( timer.elapsed() < timeout_ && in_avail() == 0 );
  246.         if( in_avail() == 0 )
  247.             {
  248.             errFlags |= TIMEOUT;
  249.             return EOF;
  250.             }
  251.         }
  252.     return (unsigned char) *(gptr());
  253.     }
  254.  
  255. int combuf::do_sputn( const char *b, int len )
  256.     {
  257.     Timer timer;
  258.     long l;
  259.     int i, port, n;
  260.  
  261.     if( offs_ == EOF || base() == 0 || len <= 0)
  262.         return 0;
  263.  
  264.     if( pptr() == 0 )
  265.         {
  266.         port = def[offs_].portAddr;
  267.         if( (options & HW_HANDSHAKE) != 0 )
  268.             assertToPort( MCR, RTS );
  269.         if( ibdelay_ != 0 || (*b == '\r' && ildelay_ != 0) )
  270.             {
  271.             l = (*b == '\r' && ildelay_ != 0) ? ildelay_ : ibdelay_;
  272.             timer.start();
  273.             while( timer.elapsed() < l );
  274.             }
  275.  
  276.         timer.start();
  277.         while( TESTPORTBIT(port+LSR,TBE) == 0 &&
  278.                 ( (options & HW_HANDSHAKE) == 0 || TESTPORTBIT(port+MSR,CTS) != 0 ) )
  279.             if( timer.elapsed() >= timeout_ )
  280.                 {
  281.                 errFlags |= TIMEOUT;
  282.                 return 0;
  283.                 }
  284.  
  285.         if( len == 1 )
  286.             {
  287.             outportb( port, *b );
  288.             return 1;
  289.             }
  290.  
  291.         n = blen()-inSize;
  292.         setp( base()+inSize, ebuf() );
  293.         if( n >= len-1 )
  294.             {
  295.             memcpy( pptr(), b+1, len-1 );
  296.             pbump( len-1 );
  297.             outportb( port, *b );
  298.             return len;
  299.             }
  300.  
  301.         memcpy( pptr(), b+1, n );
  302.         pbump( n );
  303.         outportb( port, *b );
  304.         b += (n+1);
  305.         for( i = n+1; i < len && sputc(*b++) != EOF; i++ )
  306.             i++;
  307.         return i;
  308.         }
  309.     else
  310.         return streambuf::do_sputn( b, len );
  311.     }
  312.  
  313. int combuf::overflow( int c )
  314.     {
  315.     char b = c;
  316.     return do_sputn( &b, 1 );
  317.     }
  318.  
  319. void combuf::setBaud( long baud )
  320.     {
  321.     if( offs_ == EOF || baud < 50 || baud > 115200L )
  322.         return;
  323.     unsigned u = (unsigned) ( 115200L / baud );
  324.     assertToPort( LCR, DLAB );
  325.     outportb( def[offs_].portAddr, (u & 0xFF) );
  326.     outportb( def[offs_].portAddr+1, ((u >> 8) & 0xFF) );
  327.     unassertToPort( LCR, DLAB );
  328.     }
  329.  
  330. void combuf::setParity( int parity )
  331.     {
  332.     int i;
  333.  
  334.     if( offs_ == EOF )    return;
  335.     else if( parity == NO_PARITY )        i = 0;
  336.     else if( parity == ODD_PARITY )     i = 0x08;
  337.     else if( parity == EVEN_PARITY )    i = 0x18;
  338.     else    return;
  339.     outportb( def[offs_].portAddr+LCR, (inportb(def[offs_].portAddr+LCR) & 0xC7) | i );
  340.     }
  341.  
  342. void combuf::setBits( int bits )
  343.     {
  344.     if( offs_ == EOF || bits < 6 || bits > 8 )    return;
  345.     bits -= 5;
  346.     outportb( def[offs_].portAddr+LCR, (inportb(def[offs_].portAddr+LCR) & 0xFC) | bits );
  347.     }
  348.  
  349. void combuf::setStopBits( int bits )
  350.     {
  351.     if( offs_ == EOF || bits < 1 || bits > 2 )    return;
  352.     bits = (bits-1)*4;
  353.     outportb( def[offs_].portAddr+LCR, (inportb(def[offs_].portAddr+LCR) & 0xFB) | bits );
  354.     }
  355.  
  356. void combuf::setParams( CommProtocol& p )
  357.     {
  358.     if( offs_ == EOF )    return;
  359.     if( p.baud < 50L || p.baud > 115200L )    return;
  360.     if( p.parity < NO_PARITY || p.parity > EVEN_PARITY )    return;
  361.     if( p.bits < 6 || p.bits > 8 )    return;
  362.     if( p.stopBits != 1 && p.stopBits != 2 )    return;
  363.  
  364.     setBaud( p.baud );
  365.     setParity( p.parity );
  366.     setBits( p.bits );
  367.     setStopBits( p.stopBits );
  368.     }
  369.  
  370. void combuf::setTimeout( unsigned long l )
  371.     {
  372.     timeout_ = timeToTicks( l );
  373.     }
  374.  
  375. void combuf::setInterCharDelay( unsigned long l )
  376.     {
  377.     ibdelay_ = timeToTicks( l );
  378.     }
  379.  
  380. void combuf::setInterLineDelay( unsigned long l )
  381.     {
  382.     ildelay_ = timeToTicks( l );
  383.     }
  384.  
  385. void combuf::setPort( int p )
  386.     {
  387.     if( offs_ != EOF )
  388.         def[offs_].clrCombuf();
  389.     if( p